;; ****************************************************************************
;; *                    Driver for glasses - EXPERIMENTAL		      *
;; ****************************************************************************

	list		p=16F84A		; define processor
	#include	<p16f84a.inc>		; processor-specific defs
	
	__CONFIG	_CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC

	;; ******************************************************************
	;; Electric Connections

	#define		RED_LED		PORTA, 0    ; Activity light

	#define		LCD_BASE	PORTA, 1    ; shutter common
	#define		LCD_X		PORTA, 2    ; shutter left (?)
	#define		LCD_Y		PORTA, 3    ; shutter right (?)
	
	
	
	;; Port Tristates
	#define		trisPortA	B'00000000' ; All output
	#define		trisPortB	B'00000000' ; All output

	
	;; ******************************************************************


;; ******************************************************************
;; Useful Macros

;; Check for page boundary crossing
no_page_cross	macro	start, finish
 		if ((high start) - (high finish)) != 0
 			ERROR "Table crossed page boundary!"
 		endif
 		endm

;; Clear port shadow registers
clr_shadows	macro
 		clrf	PortA_Shadow
		clrf	PortB_Shadow
		bsf	PortB_Shadow, 0	; prevent spurious RBO interrupt
 		endm

;; Update registers from shadows to set outputs
shadows_live	macro
 		movf	PortA_Shadow, W	; load Port A Shadow
		movwf	PORTA		; update Port A
		movf	PortB_Shadow, W	; load Port B Shadow
		movwf	PORTB		; update Port B
 		endm

;; Save complete CPU state
save_state	macro
		movwf   SaveW		; save off current W register contents
		movf	STATUS, W       ; move status register into W register
		movwf	SaveStatus      ; save off contents of STATUS register
; 		movf	FSR, W		; move FSR into W
; 		movwf	SaveFSR		; save old FSR
		endm

;; Restore complete CPU state
restore_state	macro
; 		movf	SaveFSR, W	; get saved FSR
; 		movwf	FSR		; restore FSR
		movf    SaveStatus, W   ; retrieve copy of STATUS register
		movwf	STATUS          ; restore STATUS register contents
		swapf   SaveW, F
		swapf   SaveW, W        ; restore W register contents
		endm


;; ******************************************************************
	
	;; ******************************************************************
	;; Variables
	cblock		0x0c
	;; Port Shadows
		PortA_Shadow	; Shadow to prevent hazard
		PortB_Shadow	; 
	;; For interrupt handler state save/restore
		SaveW 		; save/restore W register in interrupt handler
		SaveStatus 	; save/restore status register
;; 		SaveFSR		; save/restore FSR
		NextInt		; contents of INTCON register for next interrupt


		SDL
		del_A
		del_B
		del_C
	
	endc

;;; 	cblock		0
;;; 		RX_SHADOW  ; receive buffer
;;; 		BYTE_READY ; a byte must be interpreted
;;; 		NEW_OUTPUTS ; time to recalculate outputs
;;; 	endc

;;; 	cblock		0	; Valve Flags
;;; 		A_DIR		;
;;; 		B_DIR		;
;;; 		C_DIR		; Joint direction control (0 = '-', 1 = '+')
;;; 		D_DIR		;
;;; 		E_DIR		;
;;; 		F_DIR		;
;;; 	endc
	
	;; ******************************************************************
	ORG	0x000		; processor reset vector
 	goto	init		; go to beginning of program
	ORG	0x004		; interrupt vector location
	;; Interrupt Service Routine
;;; 	save_state		; Save CPU State

	
;;; 	restore_state		; Restore CPU State
	retfie                  ; return from interrupt

	;; End of Interrupt Service Routine
	;; ******************************************************************


	;; ******************************************************************
init
	;; Initialize I/O ports
	bcf	INTCON, GIE	; disable interrupts
	bcf	STATUS, RP0	; set bank zero
	clrf	PORTA		; clear port A
	clrf	PORTB		; clear port B
	bsf	STATUS, RP0	; set bank one
	movlw	trisPortA	; load port A tristates into W
	movwf	TRISA		; set port A tristates
	movlw	trisPortB	; load port B tristates into W
	movwf	TRISB		; set port B tristates
	
	;; Set up timer
;;; 	clrf	OPTION_REG	;
;;; 	bsf	OPTION_REG, PSA	; timer: turn prescaler OFF
 	bcf	STATUS, RP0	; set bank zero
	;; Initialize interrupts
;;; 	clrf	INTCON
;;; 	bsf	INTCON, T0IE	; Timer overflow interrupt enabled
	;; Initialize counters
;;; 	clr_shadows		; blank output shadow registers

	
;;; 	bsf	PORTB, 6

	;; test
;; stupid
;; 	bsf	RED_LED
;; 	call	wait
;; 	bcf	RED_LED
;; 	call	wait
;; 	goto	stupid


lcd_test
	bcf	LCD_BASE
	bsf	LCD_X
	bsf	LCD_Y
 	call	del_1ms
	bsf	LCD_BASE
	bcf	LCD_X
	bcf	LCD_Y
 	call	del_1ms
	goto	lcd_test
	


	

;; wait
;; 	movlw	D'250'
;; 	movwf	SDL
;; 	call	delay_ms
;; 	return

	

                ; ************************ Delay_Ms ***********************
delay_ms        ; delay SDL ms at 4MHz clk ( = 1Mhz inst.); 1ms = 1000 cyc.
                movf    SDL,w
                xorlw   D'1'
                skpnz
                goto    shortdel
                movf    SDL,w
                movwf   del_C
del_loop
                call    del_1ms
                decfsz  del_C,f
                goto    del_loop
                return
shortdel
                movlw   D'255'
                movwf   del_C
swait
                decfsz  del_C,f
                goto    swait
                return
                ; ************************ Delay_1Ms **********************
del_1ms
                ;981 cycles
                movlw   0x0e
                movwf   del_A
Delay_00
                movlw   0x16
                movwf   del_B
Delay_01
                decfsz  del_B, f
                goto    Delay_01
                decfsz  del_A, f
                goto    Delay_00
                ;13 cycles
                movlw   0x04
                movwf   del_A
Delay_10
                decfsz  del_A, f
                goto    Delay_10
                ;2 cycles
                goto    $+1
                ;4 cycles (including call)
                return
                ; *********************************************************
	
	END

	